package service.calculator.sonic;

import java.math.BigDecimal;

import models.Payment;
import models.Rate;
import service.BillingCalculator;
import util.Rounder;

public class SonicBillingCalculatorImpl implements BillingCalculator {

	public BigDecimal calculatePayment(Rate rate, Payment payment) {
		BigDecimal paymentCalculation = null;
		SonicPaymentType paymentType = SonicPaymentType
				.valueOf(payment.paymentType);
		BigDecimal paymentHrs = BigDecimal.valueOf(payment.hours);

		switch (paymentType) {
		case BASIC:
			BigDecimal basicBillingRate = calculateBasicBillingRate(rate);
			paymentCalculation = basicBillingRate.multiply(paymentHrs);
			break;
		case OT:
			BigDecimal otRate = rate.value.add(rate.value.multiply(BigDecimal
					.valueOf(0.25)));
			paymentCalculation = otRate.multiply(paymentHrs);
			break;
		case RDRT:
			BigDecimal hpRate = rate.value.add(rate.value.multiply(BigDecimal
					.valueOf(0.30)));
			paymentCalculation = hpRate.multiply(paymentHrs);
			break;
		case SHOT:
        case RDOT:
            // (BasicRate x 1.3) + ((BasicRate x 1.3) x 30%)
            BigDecimal shotRate = rate.value.multiply(BigDecimal.valueOf(1.3));
            shotRate = shotRate.add(shotRate.multiply(BigDecimal.valueOf(0.30)));
            paymentCalculation = shotRate.multiply(paymentHrs);
            break;
		case LHRT:
			paymentCalculation = rate.value.multiply(paymentHrs);
			break;
		case LHOT:
            // (BasicRate x 2) + ((BasicRate x 2) x 30%)
        	BigDecimal lhotRate = rate.value.add(rate.value.multiply(BigDecimal.valueOf(1)));
            lhotRate = lhotRate.add(lhotRate.multiply(BigDecimal.valueOf(0.30)));
            paymentCalculation = lhotRate.multiply(paymentHrs);
            break;
		case SHRT:
			BigDecimal shrtRate = rate.value.multiply(BigDecimal.valueOf(0.30));
			paymentCalculation = shrtRate.multiply(paymentHrs);
			break;
		case NDRT:
			BigDecimal ndrtRate = rate.value.multiply(BigDecimal
					.valueOf(0.1001));
			paymentCalculation = ndrtRate.multiply(paymentHrs);
			break;
		case NDOT:
        	// Only 13% of the rate (10% of rate bec. of ND plus 3% bec. of SH)
            BigDecimal ndshRate = rate.value.multiply(BigDecimal.valueOf(0.13));
            paymentCalculation = ndshRate.multiply(paymentHrs);
            break;
		case CTPA:
			paymentCalculation = BigDecimal.valueOf(12.50).multiply(paymentHrs);
			break;
		case SEA:
			paymentCalculation = BigDecimal.valueOf(13.00).multiply(paymentHrs);
			break;
		default:
			System.out.println("WARNING: " + payment.paymentType
					+ " payment type not yet supported.");
		}

		if (paymentCalculation != null) {
			paymentCalculation = Rounder.roundup(paymentCalculation);
		}

		return paymentCalculation;
	}

	private BigDecimal calculateBasicBillingRate(final Rate rate) {
		BigDecimal basicRate = BigDecimal.valueOf(0.00);
		BigDecimal governmentBenefits = computeGovernmentBenefitsPerHour();

		basicRate = basicRate.add(rate.value);
		basicRate = basicRate.add(governmentBenefits);

		return basicRate;
	}

	protected BigDecimal computeGovernmentBenefitsPerHour() {
		// Per day is computed by monthly/26 days.
		BigDecimal thirteenthMonthPayPerDay = BigDecimal.valueOf(25.83);
		BigDecimal sssPerDay = BigDecimal.valueOf(22.67);
		BigDecimal philhealthPerDay = BigDecimal.valueOf(3.85);
		BigDecimal pagIbigPerDay = BigDecimal.valueOf(3.85);
		BigDecimal ecMcPerDay = BigDecimal.valueOf(0.38);

		BigDecimal governmentBenefits = BigDecimal.valueOf(0.00);
		governmentBenefits = governmentBenefits.add(thirteenthMonthPayPerDay);
		governmentBenefits = governmentBenefits.add(sssPerDay);
		governmentBenefits = governmentBenefits.add(philhealthPerDay);
		governmentBenefits = governmentBenefits.add(pagIbigPerDay);
		governmentBenefits = governmentBenefits.add(ecMcPerDay);

		// Compute per hour
		governmentBenefits = governmentBenefits.divide(BigDecimal.valueOf(8));

		return governmentBenefits;
	}

}
